package com.meida.bpm.provider.common.service.impl;

import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.meida.bpm.provider.common.service.IBaseFlowableService;
import com.meida.bpm.provider.constant.FlowableConstant;
import com.meida.bpm.provider.listener.FlowListInterceptor;
import com.meida.bpm.provider.listener.FlowPageInterceptor;
import com.meida.bpm.provider.service.ProcessInstanceService;
import com.meida.common.base.entity.EntityMap;
import com.meida.common.mybatis.model.PageParams;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaQuery;
import com.meida.common.base.utils.FlymeUtils;
import com.meida.common.utils.SpringContextHolder;
import org.flowable.common.engine.api.query.Query;
import org.flowable.common.engine.api.query.QueryProperty;
import org.flowable.task.service.impl.HistoricTaskInstanceQueryProperty;
import org.flowable.task.service.impl.TaskQueryProperty;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zyf
 */
public abstract class BaseFlowableServiceImpl implements IBaseFlowableService {

    public static Map<String, QueryProperty> taskSortMap = new HashMap<>();
    public static Map<String, QueryProperty> allowedSortPropertiesTodo = new HashMap<>();

    static {
        taskSortMap.put("deleteReason", HistoricTaskInstanceQueryProperty.DELETE_REASON);
        taskSortMap.put("duration", HistoricTaskInstanceQueryProperty.DURATION);
        taskSortMap.put("endTime", HistoricTaskInstanceQueryProperty.END);
        taskSortMap.put(FlowableConstant.EXECUTION_ID, HistoricTaskInstanceQueryProperty.EXECUTION_ID);
        taskSortMap.put("taskInstanceId", HistoricTaskInstanceQueryProperty.HISTORIC_TASK_INSTANCE_ID);
        taskSortMap.put(FlowableConstant.PROCESS_DEFINITION_ID, HistoricTaskInstanceQueryProperty.PROCESS_DEFINITION_ID);
        taskSortMap.put(FlowableConstant.PROCESS_INSTANCE_ID, HistoricTaskInstanceQueryProperty.PROCESS_INSTANCE_ID);
        taskSortMap.put("assignee", HistoricTaskInstanceQueryProperty.TASK_ASSIGNEE);
        taskSortMap.put(FlowableConstant.TASK_DEFINITION_KEY, HistoricTaskInstanceQueryProperty.TASK_DEFINITION_KEY);
        taskSortMap.put("description", HistoricTaskInstanceQueryProperty.TASK_DESCRIPTION);
        taskSortMap.put("dueDate", HistoricTaskInstanceQueryProperty.TASK_DUE_DATE);
        taskSortMap.put(FlowableConstant.NAME, HistoricTaskInstanceQueryProperty.TASK_NAME);
        taskSortMap.put("owner", HistoricTaskInstanceQueryProperty.TASK_OWNER);
        taskSortMap.put("priority", HistoricTaskInstanceQueryProperty.TASK_PRIORITY);
        taskSortMap.put(FlowableConstant.TENANT_ID, HistoricTaskInstanceQueryProperty.TENANT_ID_);
        taskSortMap.put("startTime", HistoricTaskInstanceQueryProperty.START);

        allowedSortPropertiesTodo.put(FlowableConstant.PROCESS_DEFINITION_ID, TaskQueryProperty.PROCESS_DEFINITION_ID);
        allowedSortPropertiesTodo.put(FlowableConstant.PROCESS_INSTANCE_ID, TaskQueryProperty.PROCESS_INSTANCE_ID);
        allowedSortPropertiesTodo.put(FlowableConstant.TASK_DEFINITION_KEY, TaskQueryProperty.TASK_DEFINITION_KEY);
        allowedSortPropertiesTodo.put("dueDate", TaskQueryProperty.DUE_DATE);
        allowedSortPropertiesTodo.put(FlowableConstant.NAME, TaskQueryProperty.NAME);
        allowedSortPropertiesTodo.put("priority", TaskQueryProperty.PRIORITY);
        allowedSortPropertiesTodo.put(FlowableConstant.TENANT_ID, TaskQueryProperty.TENANT_ID);
        allowedSortPropertiesTodo.put("createTime", TaskQueryProperty.CREATE_TIME);
    }

    @Autowired
    public ProcessInstanceService processInstanceService;

    @Override
    public ResultBody pageList(Map params, Query query, Map<String, QueryProperty> allowedSortProperties, QueryProperty defaultDescSortProperty, FlowListInterceptor listInterceptor) {
        CriteriaQuery cq = new CriteriaQuery(params);
        EntityMap paramsMap = new EntityMap(params);
        List list;
        Boolean isPager = cq.getPager();
        PageParams pageParams = cq.getPageParams();
        Boolean hanHandler = false;
        //扩展事件
        FlowPageInterceptor flowPageInterceptor = SpringContextHolder.getHandler(cq.getHandlerName(), FlowPageInterceptor.class);
        if (FlymeUtils.isNotEmpty(flowPageInterceptor)) {
            hanHandler = true;
            flowPageInterceptor.prepare(query, paramsMap);
        }
        if (!isPager) {
            list = query.list();
        } else {
            setOrder(pageParams, query, allowedSortProperties, defaultDescSortProperty);
            list = query.listPage((int) pageParams.getOffset(), pageParams.getLimit());
        }
        //执行数据封装
        if (listInterceptor != null) {
            list = listInterceptor.execute(list);
        }
        //自定义业务数据扩展
        if (hanHandler) {
            pageParams.setRecords(flowPageInterceptor.complete(query, list, paramsMap));
        } else {
            pageParams.setRecords(list);
        }
        pageParams.setTotal(query.count());
        return ResultBody.ok(pageParams);
    }

    /**
     * 设置排序
     *
     * @param pageParams
     * @param query
     * @param properties
     * @param defaultDescSortProperty
     */
    protected void setOrder(PageParams pageParams, Query query, Map<String, QueryProperty> properties, QueryProperty defaultDescSortProperty) {
        String order = pageParams.getOrder();
        //如果有排序设置排序字段
        if (FlymeUtils.isNotEmpty(order)) {
            QueryProperty qp = properties.get(order);
            String sort = FlymeUtils.getString(pageParams.getSort(), SqlKeyword.DESC.name());
            query.orderBy(qp);
            if (sort.equals(SqlKeyword.ASC.name())) {
                query.asc();
            } else {
                query.desc();
            }
        }
    }
}
